home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2001 December / pcwk12201b.iso / Wersje pelne i specjalne / Winamp 2.77 i 3.0beta / wasabi-sdk_beta1.exe / studio / common / canvas.cpp < prev    next >
C/C++ Source or Header  |  2001-10-08  |  27KB  |  1,137 lines

  1. /*
  2.  
  3.   Nullsoft WASABI Source File License
  4.  
  5.   Copyright 1999-2001 Nullsoft, Inc.
  6.  
  7.     This software is provided 'as-is', without any express or implied
  8.     warranty.  In no event will the authors be held liable for any damages
  9.     arising from the use of this software.
  10.  
  11.     Permission is granted to anyone to use this software for any purpose,
  12.     including commercial applications, and to alter it and redistribute it
  13.     freely, subject to the following restrictions:
  14.  
  15.     1. The origin of this software must not be misrepresented; you must not
  16.        claim that you wrote the original software. If you use this software
  17.        in a product, an acknowledgment in the product documentation would be
  18.        appreciated but is not required.
  19.     2. Altered source versions must be plainly marked as such, and must not be
  20.        misrepresented as being the original software.
  21.     3. This notice may not be removed or altered from any source distribution.
  22.  
  23.  
  24.   Brennan Underwood
  25.   brennan@nullsoft.com
  26.  
  27. */
  28.  
  29. #include <windows.h>
  30. #include <ddraw.h>
  31.  
  32.  
  33. #include "blending.h"
  34. #include "canvas.h"
  35. #include "bitmap.h"
  36. #include "region.h"
  37. #include "basewnd.h"
  38. #include "fontdef.h"
  39.  
  40. #include "../studio/assert.h"
  41. #include "../studio/api.h"
  42.  
  43. #define CBCLASS Canvas
  44. START_DISPATCH;
  45.   CB(GETHDC, getHDC);
  46.   CB(GETROOTWND, getRootWnd);
  47.   CB(GETBITS, getBits);
  48.   VCB(GETOFFSETS, getOffsets);
  49.   CB(ISFIXEDCOORDS, isFixedCoords);
  50.   CB(GETDIM, getDim);
  51.   CB(GETTEXTFONT, getTextFont);
  52.   CB(GETTEXTSIZE, getTextSize);
  53.   CB(GETTEXTBOLD, getTextBold);
  54.   CB(GETTEXTOPAQUE, getTextOpaque);
  55.   CB(GETTEXTALIGN, getTextAlign);
  56.   CB(GETTEXTCOLOR, getTextColor);
  57. END_DISPATCH;
  58. #undef CBCLASS
  59.  
  60. //NONPORTABLE
  61.  
  62. Canvas::Canvas() {
  63.   hdc = NULL;
  64.   bits = NULL;
  65.   srcwnd = NULL;
  66.   fcoord = FALSE;
  67.   xoffset = yoffset = 0;
  68.  
  69.   align = DT_LEFT;
  70.   tsize = 12;
  71.   tbold = 0;
  72.   topaque = 0;
  73.   width=height=pitch=0;
  74.   tcolor = RGB(0,0,0);
  75.   tfont = new String; // using dynamic tfont here coz we need to manage em with stack, so stacking fonts won't take sizeof(String) and their destruction will not fuxor everything
  76.   tfont->setValue("Arial");
  77. //  tvariable = 0;
  78. }
  79.  
  80. Canvas::~Canvas() {
  81.   ASSERT(hdc == NULL);
  82.   delete tfont;
  83.   if (!fontstack.isempty()) {
  84.     OutputDebugString("Font stack not empty in Canvas::~Canvas !");
  85.     while (!fontstack.isempty()) {
  86.       String *s;
  87.       fontstack.pop(&s);
  88.       delete s;
  89.     }
  90.   }
  91.   if (!boldstack.isempty() || !opstack.isempty() || !alstack.isempty() || !colorstack.isempty() || !sizestack.isempty())
  92.     OutputDebugString("Font property stack not empty in Canvas::~Canvas !");
  93. }
  94.  
  95. void Canvas::setBaseWnd(BaseWnd *b) {
  96.   srcwnd=b;
  97. }
  98.  
  99. HDC Canvas::getHDC() {
  100.   return hdc;
  101. }
  102.  
  103. RootWnd *Canvas::getRootWnd() {
  104.   return srcwnd;
  105. }
  106.  
  107. void *Canvas::getBits() {
  108.   return bits;
  109. }
  110.  
  111. BOOL Canvas::getDim(int *w, int *h, int *p) {
  112.   if (w) *w=width;
  113.   if (h) *h=height;
  114.   if (p) *p=pitch;
  115.   return FALSE;
  116. }
  117.  
  118. void Canvas::getOffsets(int *x, int *y) {
  119.   if (x != NULL) *x = getXOffset();
  120.   if (y != NULL) *y = getYOffset();
  121. }
  122.  
  123. BOOL Canvas::isFixedCoords() {
  124.   return fcoord;
  125. }
  126.  
  127. BaseWnd *Canvas::getBaseWnd() {
  128.   return srcwnd;
  129. }
  130.  
  131. void Canvas::fillRect(RECT *r, COLORREF color) {
  132.   ASSERT(r != NULL);
  133.   HBRUSH brush;
  134.   if (color == RGB(0,0,0)) {
  135.     FillRect(hdc, r, (HBRUSH)GetStockObject(BLACK_BRUSH));
  136.     return;
  137.   }
  138.   RECT rr = *r;
  139.   offsetRect(&rr);
  140.  
  141.   brush = CreateSolidBrush(color);
  142.   FillRect(hdc, &rr, brush);
  143.   DeleteObject(brush);
  144. }
  145.  
  146. void Canvas::drawRect(RECT *r, int solid, COLORREF color) {
  147.   HBRUSH oldbrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH));
  148.   HPEN oldpen, pen;
  149.   pen = CreatePen(solid ? PS_SOLID : PS_DOT, 0, color);
  150.   oldpen = (HPEN)SelectObject(hdc, pen);
  151.   ASSERT(r != NULL);
  152.   RECT rr = *r;
  153.   offsetRect(&rr);
  154.   Rectangle(hdc, rr.left, rr.top, rr.right, rr.bottom);
  155.   SelectObject(hdc, oldpen);
  156.   SelectObject(hdc, oldbrush);
  157.   DeleteObject(pen);
  158. }
  159.  
  160. void Canvas::setTextAlign(int al) {
  161.     switch(al) {
  162.         case ALIGN_LEFT: align=DT_LEFT; break;
  163.         case ALIGN_CENTER: align=DT_CENTER; break;
  164.         case ALIGN_RIGHT: align=DT_RIGHT; break;
  165.     }
  166. }
  167.  
  168. int Canvas::getTextAlign() {
  169.   return align;
  170. }
  171.  
  172. void Canvas::pushTextAlign(int al) {
  173.   alstack.push(align);
  174.   align = al;
  175. }
  176.  
  177. int Canvas::popTextAlign() {
  178.   if (alstack.isempty()) return 0;
  179.   int old = align;
  180.   alstack.pop(&align);
  181.   return old;
  182. }
  183.  
  184. void Canvas::setTextOpaque(int opaque) {
  185.   topaque = opaque;
  186. }
  187.  
  188. int Canvas::getTextOpaque() {
  189.   return topaque;
  190. }
  191.  
  192. void Canvas::pushTextOpaque(int op) {
  193.   opstack.push(topaque);
  194.   topaque = op;
  195. }
  196.  
  197. int Canvas::popTextOpaque() {
  198.   if (opstack.isempty()) return 0;
  199.   int old = topaque;
  200.   opstack.pop(&topaque);
  201.   return old;
  202. }
  203.  
  204. void Canvas::setTextBold(int b) {
  205.   tbold = b;
  206. }
  207.  
  208. int Canvas::getTextBold() {
  209.   return tbold;
  210. }
  211.  
  212. void Canvas::pushTextBold(int b) {
  213.   boldstack.push(tbold);
  214.   tbold = b;
  215. }
  216.  
  217. int Canvas::popTextBold() {
  218.   if (boldstack.isempty()) return 0;
  219.   int old = tbold;
  220.   boldstack.pop(&tbold);
  221.   return old;
  222. }
  223.  
  224. /*void Canvas::setTextVariable(int v) {
  225.   tvariable = v;
  226. }
  227.  
  228. int Canvas::getTextVariable() {
  229.   return tvariable;  
  230. }
  231.  
  232. void Canvas::pushTextVariable(int v) {
  233.   varstack.push(tvariable);
  234.   tvariable = v;
  235. }
  236.  
  237. int Canvas::popTextVariable() {
  238.   int old = tvariable;
  239.   varstack.pop(&tvariable);
  240.   return old;
  241. } */
  242.  
  243. void Canvas::setTextColor(COLORREF color) {
  244.   tcolor = color;
  245. }
  246.  
  247. COLORREF Canvas::getTextColor() {
  248.   return tcolor;
  249. }
  250.  
  251. void Canvas::pushTextColor(COLORREF color) {
  252.   colorstack.push(tcolor);
  253.   tcolor = color;
  254. }
  255.  
  256. COLORREF Canvas::popTextColor() {
  257.   if (colorstack.isempty()) return RGB(0,0,0);
  258.   COLORREF oldcolor = tcolor;
  259.   colorstack.pop(&tcolor);
  260.   return oldcolor;
  261. }
  262.  
  263. void Canvas::setTextSize(int points) {
  264.   tsize = points;
  265. }
  266.  
  267. int Canvas::getTextSize() {
  268.   return tsize;
  269. }
  270.  
  271. void Canvas::pushTextSize(int point) {
  272.   sizestack.push(tsize);
  273.   tsize = point;
  274. }
  275.  
  276. int Canvas::popTextSize() {
  277.   if (sizestack.isempty()) return 0;
  278.   int oldsize = tsize;
  279.   sizestack.pop(&tsize);
  280.   return oldsize;
  281. }
  282.  
  283. void Canvas::setTextFont(const char *font_id_name) {
  284.   tfont->setValue(font_id_name);
  285. }
  286.  
  287. const char *Canvas::getTextFont() {
  288.   return tfont->getValue();
  289. }
  290.  
  291. void Canvas::pushTextFont(const char *font_id_name) {
  292.   fontstack.push(tfont);
  293.   tfont = new String;
  294.   tfont->setValue(font_id_name);
  295. }
  296.  
  297. const char *Canvas::popTextFont() {
  298.   if (fontstack.isempty()) return NULL;
  299.   String *old = tfont;
  300.   fontstack.pop(&tfont);
  301.   Canvas::retfontname[0] = 0;
  302.   if (!old->isempty())
  303.     STRCPY(Canvas::retfontname, old->getValue());
  304.   delete old;
  305.   return Canvas::retfontname;
  306. }
  307.  
  308. void Canvas::moveTo(int x, int y) {
  309. MoveToEx(hdc, x, y, NULL);
  310. }
  311.  
  312. void Canvas::lineTo(int x, int y) {
  313. LineTo(hdc, x, y);
  314. }
  315.  
  316. void Canvas::textOut(int x, int y, const char *txt) {
  317.   api->font_textOut(this, WA_FONT_TEXTOUT_NORMAL, x, y, 0, 0, txt);
  318. }
  319.  
  320. void Canvas::textOut(int x, int y, int w, int h, const char *txt) {
  321.   api->font_textOut(this, WA_FONT_TEXTOUT_RECT, x, y, w, h, txt);
  322. }
  323.  
  324. void Canvas::textOutEllipsed(int x, int y, int w, int h, const char *txt) {
  325.   api->font_textOut(this, WA_FONT_TEXTOUT_ELLIPSED, x, y, w, h, txt);
  326. }
  327.  
  328. void Canvas::textOutWrapped(int x, int y, int w, int h, const char *txt) {
  329.   api->font_textOut(this, WA_FONT_TEXTOUT_WRAPPED, x, y, w, h, txt);
  330. }
  331.  
  332. void Canvas::textOutWrappedPathed(int x, int y, int w, const char *txt) {
  333.   api->font_textOut(this, WA_FONT_TEXTOUT_WRAPPEDPATHED, x, y, w, 0, txt);
  334. }
  335.  
  336. void Canvas::textOutCentered(RECT *r, const char *txt) {
  337.   api->font_textOut(this, WA_FONT_TEXTOUT_CENTERED, r->left, r->top, r->right, r->bottom, txt);
  338. }
  339.  
  340. int Canvas::getTextWidth(const char *text) {
  341.   return api->font_getInfo(this, tfont->getValue(), WA_FONT_GETINFO_WIDTH, text, NULL, NULL);
  342. }
  343.  
  344. int Canvas::getTextHeight(const char *text) {
  345.   return api->font_getInfo(this, tfont->getValue(), WA_FONT_GETINFO_HEIGHT, text, NULL, NULL);
  346. }
  347.  
  348. void Canvas::getTextExtent(const char *txt, int *w, int *h) {
  349.   api->font_getInfo(this, tfont->getValue(), WA_FONT_GETINFO_WIDTHHEIGHT, txt, w, h);
  350. }
  351.  
  352. void Canvas::offsetRect(RECT *r) {
  353.   ASSERT(r != NULL);
  354.   r->left += xoffset;
  355.   r->right += xoffset;
  356.   r->top += yoffset;
  357.   r->bottom += yoffset;
  358. }
  359.  
  360. void Canvas::selectClipRgn(Region *r) {
  361.     SelectClipRgn(hdc, r ? r->getHRGN() : NULL);
  362. }
  363.  
  364. int Canvas::getClipBox(RECT *r) {
  365.   return GetClipBox(hdc, r);
  366. }
  367.  
  368. int Canvas::getClipRgn(Region *r) {
  369.   ASSERT(r != NULL);
  370.   return GetClipRgn(hdc, r->getHRGN());
  371. }
  372.  
  373. //FG> added blit canvas to canvas
  374. void Canvas::blit(int srcx, int srcy, Canvas *dest, int dstx, int dsty, int dstw, int dsth) { 
  375.   char *srcbits=(char *)getBits();
  376.   char *destbits=(char *)dest->getBits();
  377.   RECT clipr;
  378.   if (srcbits && destbits && GetClipBox(dest->getHDC(),&clipr) == SIMPLEREGION)
  379.   {
  380.     int srcimg_w,srcimg_h,srcimg_p;
  381.     getDim(&srcimg_w,&srcimg_h,&srcimg_p);
  382.     int dstimg_w,dstimg_h,dstimg_p;
  383.     dest->getDim(&dstimg_w,&dstimg_h,&dstimg_p);
  384.     
  385.     if (srcx < 0) { dstx-=srcx; dstw+=srcx; srcx=0; }
  386.     if (srcy < 0) { dsty-=srcy; dsth+=srcy; srcy=0; }
  387.     if (srcx+dstw >= srcimg_w) dstw=srcimg_w-srcx;
  388.     if (srcy+dsth >= srcimg_h) dsth=srcimg_h-srcy;
  389.  
  390.     if (dstx < clipr.left) { srcx+=clipr.left-dstx; dstw-=clipr.left-dstx; dstx=clipr.left; }
  391.     if (dsty < clipr.top) { srcy+=clipr.top-dsty; dsth-=clipr.top-dsty; dsty=clipr.top; }
  392.  
  393.     if (dstx+dstw >= clipr.right) dstw=clipr.right-dstx;
  394.     if (dsty+dsth >= clipr.bottom) dsth=clipr.bottom-dsty;
  395.  
  396.     if (!dstw || !dsth) return;
  397.  
  398.     int y;
  399.     int yl=dsty+dsth;
  400.     for (y = dsty; y < yl; y++)
  401.     {
  402.       MEMCPY(destbits+y*dstimg_p+dstx*4,srcbits+srcy*srcimg_p+srcx*4,dstw*4);
  403.       srcy++;
  404.     }
  405.   }
  406.   else
  407.   {
  408.     GdiFlush();
  409.     BitBlt(dest->getHDC(), dstx, dsty, dstw, dsth, getHDC(), srcx, srcy, SRCCOPY);
  410.   }
  411. }
  412.  
  413. // src* are in fixed point
  414. void Canvas::stretchblit(int srcx, int srcy, int srcw, int srch, Canvas *dest, int dstx, int dsty, int dstw, int dsth) { 
  415.   GdiFlush();
  416.   int done=0;
  417.   void *srcdib=getBits();
  418.  
  419.   if (!dstw || !dsth || !srcw || !srch) return;
  420.   if (srcdib)
  421.   {
  422.     int srcdib_w, srcdib_h, srcdib_p;
  423.     getDim(&srcdib_w,&srcdib_h,&srcdib_p);
  424.     int nofilter=0;//FUCKO :) _intVal(api->config_enumRootCfgItem(0), "NoWindowStretchFilter");
  425.  
  426.     void *dstdib;
  427.     BITMAPINFO dstbmi={0,};
  428.     HDC hMemDC;
  429.     HBITMAP hsrcdib;
  430.     dstbmi.bmiHeader.biSize=sizeof(dstbmi.bmiHeader);
  431.     dstbmi.bmiHeader.biWidth=dstw;
  432.     dstbmi.bmiHeader.biHeight=-ABS(dsth);
  433.     dstbmi.bmiHeader.biPlanes=1;
  434.     dstbmi.bmiHeader.biBitCount=32;
  435.     dstbmi.bmiHeader.biCompression=BI_RGB;
  436.     hMemDC = CreateCompatibleDC(NULL);
  437.     hsrcdib=CreateDIBSection(hMemDC,&dstbmi,DIB_RGB_COLORS,&dstdib,NULL,0);
  438.     if (hsrcdib)
  439.     {
  440.       HBITMAP hprev=(HBITMAP)SelectObject(hMemDC,hsrcdib);
  441.  
  442.       int y;
  443.       int SY, dX, dY;
  444.       int Xend=(srcdib_w-2)<<16;
  445.       SY=srcy;
  446.       dX=srcw/dstw;
  447.       dY=srch/dsth;
  448.  
  449.       int xstart=0;
  450.       int xp=srcx>>16;
  451.       if (xp < 0) 
  452.       {
  453.         xstart=-xp;
  454.         srcx+=xstart*dX;
  455.       }
  456.  
  457.       int xend=dstw;
  458.       xp=(srcx+(dX*(xend-xstart)))>>16;
  459.       if (xp > srcdib_w)
  460.       {
  461.         xend=xstart+srcdib_w - (srcx>>16);
  462.       }
  463.     
  464.       for (y = 0; y < dsth; y ++)
  465.       {
  466.         int yp=(SY>>16);
  467.         if (yp >= 0)
  468.         {
  469.           int x;
  470.           int SX=srcx;
  471.           unsigned int *out=(unsigned int*)dstdib + xstart + y*dstw;
  472.           int end=yp >= srcdib_h-1;
  473.           if (nofilter || end) 
  474.           {
  475.             if (end) yp=srcdib_h-1;
  476.             unsigned int *in=(unsigned int*) ((char *)srcdib + yp*srcdib_p);
  477.             for (x = xstart; x < xend; x ++) // quick hack to draw last line
  478.             {
  479.               *out++=in[SX>>16];
  480.               SX+=dX;
  481.             }
  482.             if (end) break;
  483.           }
  484.           else
  485.           {
  486.             unsigned int *in=(unsigned int*) ((char *)srcdib + yp*srcdib_p);
  487.  
  488.   #ifndef NO_MMX
  489.             if (Blenders::MMX_AVAILABLE())
  490.             {
  491.               for (x = xstart; x < xend; x ++)
  492.               {
  493.                 if (SX>Xend) *out++=Blenders::BLEND4_MMX(in+(Xend>>16),srcdib_w,0xffff,SY);
  494.                 else *out++=Blenders::BLEND4_MMX(in+(SX>>16),srcdib_w,SX,SY);
  495.                 SX+=dX;
  496.               }
  497.             }
  498.             else
  499.   #endif
  500.             {
  501.               for (x = xstart; x < xend; x ++)
  502.               {
  503.                 if (SX>Xend) *out++=Blenders::BLEND4(in+(Xend>>16),srcdib_w,0xffff,SY);
  504.                 else *out++=Blenders::BLEND4(in+(SX>>16),srcdib_w,SX,SY);
  505.                 SX+=dX;
  506.               }
  507.             }
  508.           }
  509.         }
  510.         SY+=dY;
  511.       }
  512.  
  513.  
  514. #ifndef NO_MMX
  515.       Blenders::BLEND_MMX_END();
  516. #endif
  517.  
  518.  
  519.       BitBlt(dest->getHDC(),dstx,dsty,dstw,dsth,hMemDC,0,0,SRCCOPY);
  520.       done++;
  521.  
  522.       SelectObject(hMemDC,hprev);
  523.       DeleteObject(hsrcdib);
  524.     }
  525.     DeleteDC(hMemDC);
  526.   }
  527.  
  528.   if (!done)
  529.   {
  530.     SetStretchBltMode(dest->getHDC(),COLORONCOLOR);
  531.     StretchBlt(dest->getHDC(), dstx, dsty, dstw, dsth, getHDC(), srcx>>16, srcy>>16, srcw>>16, srch>>16, SRCCOPY);
  532.   }
  533. }
  534.  
  535. void Canvas::debug() {
  536. #ifdef DEBUG_SCREEN_SHIFT
  537.   Canvas *c = new SysCanvas();
  538.   int w, h;
  539.   getDim(&w, &h, NULL);
  540.   blit(0, 0, c, DEBUG_SCREEN_SHIFT, 0, w, h);
  541.   delete c;
  542. #endif
  543. }
  544.  
  545.  
  546. #define BF2 (~((3<<24)|(3<<16)|(3<<8)|3))
  547.  
  548. void Canvas::antiAliasTo(Canvas *dest, int w, int h, int aafactor) {
  549.   ASSERT(aafactor != 0);
  550.   if (aafactor == 1) {
  551.     blit(0, 0, dest, 0, 0, w, h);
  552.     return;
  553.   }
  554.   ASSERT(getBits() != NULL);
  555.   ASSERT(dest->getBits() != NULL);
  556.   if (getBits() == NULL || dest->getBits() == NULL) return;
  557.   ASSERTPR(aafactor <= 2, "too lazy to generalize the code right now :)");
  558.   GdiFlush();
  559.   // we should really store the bpp too
  560.   int aaw = w * aafactor;
  561.   unsigned long *s1 = (unsigned long *)getBits(), *s2 = s1 + 1;
  562.   unsigned long *s3 = s1 + aaw, *s4 = s3 + 1;
  563.   unsigned long *d = (unsigned long *)dest->getBits();
  564. #if 1
  565.   for (int y = 0; y < h; y++) {
  566.     for (int x = 0; x < w; x++) {
  567.       unsigned long tmp = ((*s1 & BF2)>>2) + ((*s2 & BF2)>>2) + ((*s3 & BF2)>>2) + ((*s4 & BF2)>>2); 
  568.       *d++ = tmp;
  569.  
  570.       s1 += 2; s2 += 2;
  571.       s3 += 2; s4 += 2;
  572.     }
  573.     s1 += aaw; s2 += aaw;
  574.     s3 += aaw; s4 += aaw;
  575.   }
  576. #else
  577. for (int x = 0; x < w * h; x++) d[x] = s1[x];
  578. #endif
  579. }
  580.  
  581. char Canvas::retfontname[256];
  582.  
  583. WndCanvas::WndCanvas() {
  584.   hWnd = NULL;
  585. }
  586.  
  587. WndCanvas::~WndCanvas() {
  588.   ASSERT((hWnd != NULL && hdc != NULL) || (hWnd == NULL && hdc == NULL));
  589.   if (hWnd != NULL) ReleaseDC(hWnd, hdc);
  590.   hdc = NULL;
  591. }
  592.  
  593. int WndCanvas::attachToClient(BaseWnd *basewnd) {
  594.   ASSERT(basewnd != NULL);
  595.   hWnd = basewnd->gethWnd();
  596.   ASSERT(hWnd != NULL);
  597.   hdc = GetDC(hWnd);
  598.   ASSERT(hdc != NULL);
  599.   srcwnd = basewnd;
  600.   return 1;
  601. }
  602.  
  603. #if 0//CUT
  604. int WndCanvas::attachToWnd(HWND _hWnd) {
  605.   hWnd = _hWnd;
  606.   ASSERT(hWnd != NULL);
  607.   hdc = GetWindowDC(hWnd);
  608.   ASSERT(hdc != NULL);
  609.   return 1;
  610. }
  611. #endif
  612.  
  613. PaintCanvas::PaintCanvas() {
  614.   hWnd = NULL;
  615. }
  616.  
  617. PaintCanvas::~PaintCanvas() {
  618.   
  619.   if (hdc != NULL) EndPaint(hWnd, &ps);
  620.   hdc = NULL;
  621. }
  622.  
  623. void PaintCanvas::getRcPaint(RECT *r) {
  624.   *r = ps.rcPaint; 
  625. }
  626.  
  627. int PaintCanvas::beginPaint(BaseWnd *basewnd) {
  628.   hWnd = basewnd->gethWnd();    // NONPORTABLE
  629.   ASSERT(hWnd != NULL);
  630.   hdc = BeginPaint(hWnd, &ps);
  631.   ASSERT(hdc != NULL);
  632.   srcwnd = basewnd;
  633.   return 1;
  634. }
  635.  
  636. PaintBltCanvas::PaintBltCanvas() {
  637.   hWnd = NULL;
  638.   wnddc = NULL;
  639.   hbmp = NULL;
  640.   prevbmp = NULL;
  641.   bits = NULL;
  642.   fcoord = TRUE;
  643.   nonclient = FALSE;
  644. }
  645.  
  646. PaintBltCanvas::~PaintBltCanvas() {
  647.   RECT r;
  648.  
  649.   if (hdc == NULL) return;
  650.  
  651.   ASSERT(srcwnd != NULL);
  652.     if (nonclient) //FG> nonclient painting fix
  653.         srcwnd->getNonClientRect(&r);
  654.     else
  655.         srcwnd->getClientRect(&r); 
  656.  
  657.   // blt here
  658.   GdiFlush();
  659.   BitBlt(wnddc, r.left, r.top, r.right-r.left, r.bottom-r.top, hdc, 0, 0, SRCCOPY);
  660.  
  661.   //SelectClipRgn(hdc, NULL);
  662.   // kill the bitmap and its DC
  663.   SelectObject(hdc, prevbmp);
  664.   DeleteDC(hdc);
  665.   hdc = NULL;
  666.   DeleteObject(hbmp);
  667.   bits=NULL;
  668.   width=0;
  669.   height=0;
  670.   pitch=0;
  671.  
  672.   EndPaint(hWnd, &ps);    // end of wnddc
  673.   wnddc = NULL;
  674. }
  675.  
  676. //FG> nonclient painting fix
  677. int PaintBltCanvas::beginPaintNC(BaseWnd *basewnd) {
  678.   nonclient = TRUE;
  679.   return beginPaint(basewnd);
  680. }
  681.  
  682. void PaintBltCanvas::getRcPaint(RECT *r) {
  683.   *r = ps.rcPaint; 
  684. }
  685.  
  686. int PaintBltCanvas::beginPaint(BaseWnd *basewnd) {
  687.  
  688.   RECT r;
  689.   
  690.   if (nonclient)
  691.     basewnd->getNonClientRect(&r); //FG> nonclient painting fix
  692.   else
  693.     basewnd->getClientRect(&r);
  694.  
  695.   if (r.right - r.left <= 0 || r.bottom - r.top <= 0) return 0;
  696.  
  697.   hWnd = basewnd->gethWnd();    // NONPORTABLE
  698.   ASSERT(hWnd != NULL);
  699.  
  700.   BITMAPINFO bmi;
  701.   ZeroMemory(&bmi, sizeof bmi);
  702.   bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  703.   bmi.bmiHeader.biWidth = r.right - r.left;
  704.   bmi.bmiHeader.biHeight = -(r.bottom - r.top);
  705.   bmi.bmiHeader.biPlanes = 1;
  706.   bmi.bmiHeader.biBitCount = 32;
  707.   bmi.bmiHeader.biCompression = BI_RGB;
  708.   bmi.bmiHeader.biSizeImage = 0;
  709.   bmi.bmiHeader.biXPelsPerMeter = 0;
  710.   bmi.bmiHeader.biYPelsPerMeter = 0;
  711.   bmi.bmiHeader.biClrUsed = 0;
  712.   bmi.bmiHeader.biClrImportant = 0;
  713.  
  714.   wnddc = BeginPaint(hWnd, &ps);
  715.  
  716.   ASSERT(wnddc != NULL);
  717.  
  718.   GdiFlush();
  719.   width=r.right-r.left;
  720.   height=-ABS(r.bottom-r.top);
  721.   pitch=width*4;
  722.   hbmp = CreateDIBSection(wnddc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);  
  723.  
  724.   if (hbmp == NULL) {
  725.     EndPaint(hWnd, &ps);    // end of wnddc
  726.     wnddc = NULL;
  727.     return 0;
  728.   }
  729.  
  730.   // create tha DC
  731.   hdc = CreateCompatibleDC(wnddc);
  732.   if (hdc == NULL) {
  733.     DeleteObject(hbmp);
  734.     EndPaint(hWnd, &ps);    // end of wnddc
  735.     wnddc = NULL;
  736.     return 0;
  737.   }
  738.   prevbmp = (HBITMAP)SelectObject(hdc, hbmp);
  739.  
  740.   Region *clip = new Region(&ps.rcPaint);
  741.   
  742.   selectClipRgn(clip);
  743.  
  744.   delete clip;
  745.  
  746.   srcwnd = basewnd;
  747.  
  748.   return 1;
  749. }
  750.  
  751. void *PaintBltCanvas::getBits() {
  752.   return bits;
  753. }
  754.  
  755. MemCanvas::MemCanvas() {
  756. }
  757.  
  758. MemCanvas::~MemCanvas() {
  759.   DeleteDC(hdc);
  760.   hdc = NULL;
  761. }
  762.  
  763. int MemCanvas::createCompatible(Canvas *canvas) {
  764.   ASSERT(canvas != NULL);
  765.   ASSERT(canvas->getHDC() != NULL);
  766.   hdc = CreateCompatibleDC(canvas->getHDC());
  767.   ASSERT(hdc != NULL);
  768.   srcwnd = canvas->getBaseWnd();
  769.   return 1;
  770. }
  771.  
  772. DCCanvas::DCCanvas(HDC clone, BaseWnd *srcWnd) {
  773.   if (clone != NULL) cloneDC(clone, srcWnd);
  774. }
  775.  
  776. DCCanvas::~DCCanvas() {
  777.   hdc = NULL;
  778. }
  779.  
  780. int DCCanvas::cloneDC(HDC clone, BaseWnd *srcWnd) {
  781.  
  782.   ASSERT(clone != NULL);
  783.   hdc = clone;
  784.   srcwnd = srcWnd;
  785.   return 1;
  786. }
  787.  
  788. SysCanvas::SysCanvas() {
  789.   hdc = GetDC(NULL);
  790. }
  791.  
  792. SysCanvas::~SysCanvas() {
  793.   ReleaseDC(NULL, hdc);
  794.   hdc = NULL;
  795. }
  796.  
  797. DCBltCanvas::DCBltCanvas() {
  798.   origdc = NULL;
  799.   hbmp = prevbmp = NULL;
  800. }
  801.  
  802. DCBltCanvas::~DCBltCanvas() {
  803.  
  804.     commitDC();
  805.  
  806.   // kill the bitmap and its DC
  807.   SelectObject(hdc, prevbmp);
  808.   DeleteDC(hdc);
  809.   hdc = NULL;
  810.   DeleteObject(hbmp);
  811.  
  812.   // don't kill origdc, it's been cloned
  813. }
  814.  
  815. int DCBltCanvas::setOrigDC(HDC neworigdc) { // FG> allows custom draw on lists to be much faster
  816.     origdc = neworigdc;
  817.     return 1;
  818. }
  819.  
  820. int DCBltCanvas::commitDC(void) { //FG
  821.  
  822.     if (origdc) {
  823.  
  824.       RECT c;
  825.  
  826.       if (GetClipBox(origdc, &c) == NULLREGION)
  827.             c = rect;
  828.         
  829.       // shlap it down in its original spot
  830.     GdiFlush();
  831.       BitBlt(origdc, c.left, c.top,
  832.              c.right-c.left, c.bottom-c.top, hdc, c.left, c.top, SRCCOPY);
  833.  
  834.     }
  835.  
  836.     return 1;
  837. }
  838.  
  839. int DCBltCanvas::cloneDC(HDC clone, RECT *r, BaseWnd *srcWnd) {
  840.   origdc = clone;
  841.  
  842.   srcwnd = srcWnd;
  843.  
  844.   ASSERT(r != NULL);
  845.   rect = *r;
  846.  
  847. #if 1
  848.   BITMAPINFO bmi;
  849.   ZeroMemory(&bmi, sizeof bmi);
  850.   bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  851.   bmi.bmiHeader.biWidth = r->right - r->left;
  852.   bmi.bmiHeader.biHeight = -ABS(r->bottom - r->top);
  853.   bmi.bmiHeader.biPlanes = 1;
  854.   bmi.bmiHeader.biBitCount = 32;
  855.   bmi.bmiHeader.biCompression = BI_RGB;
  856.   bmi.bmiHeader.biSizeImage = 0;
  857.   bmi.bmiHeader.biXPelsPerMeter = 0;
  858.   bmi.bmiHeader.biYPelsPerMeter = 0;
  859.   bmi.bmiHeader.biClrUsed = 0;
  860.   bmi.bmiHeader.biClrImportant = 0;
  861.   hbmp = CreateDIBSection(origdc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
  862.   width=bmi.bmiHeader.biWidth;
  863.   height=ABS(bmi.bmiHeader.biHeight);
  864.   pitch=width*4;
  865. #else
  866.   hbmp = CreateCompatibleBitmap(clone, r->right - r->left, r->bottom - r->top);
  867. #endif
  868.   ASSERT(hbmp != NULL);
  869.  
  870.   // create tha DC
  871.   hdc = CreateCompatibleDC(origdc);
  872.   prevbmp = (HBITMAP)SelectObject(hdc, hbmp);
  873.  
  874.   // adjust their rect for them
  875.   r->right -= r->left;
  876.   r->left = 0;
  877.   r->bottom -= r->top;
  878.   r->top = 0;
  879.  
  880.   return 1;
  881. }
  882.  
  883.  
  884. BaseCloneCanvas::BaseCloneCanvas(CanvasBase *cloner) {
  885.   if (cloner != NULL) clone(cloner);
  886. }
  887.  
  888. int BaseCloneCanvas::clone(CanvasBase *cloner) {
  889.   ASSERTPR(hdc == NULL, "can't clone twice");
  890.   hdc = cloner->getHDC();
  891.   bits = cloner->getBits();
  892.   cloner->getDim(&width,&height,&pitch);
  893. //  srcwnd = cloner->getBaseWnd();
  894.   cloner->getOffsets(&xoffset, &yoffset);
  895.   setTextFont(cloner->getTextFont());
  896.   setTextSize(cloner->getTextSize());
  897.   setTextBold(cloner->getTextBold());
  898.   setTextOpaque(cloner->getTextOpaque());
  899.   setTextAlign(cloner->getTextAlign());
  900.   setTextColor(cloner->getTextColor());
  901.   return (hdc != NULL);
  902. }
  903.  
  904. BaseCloneCanvas::~BaseCloneCanvas() {
  905.   hdc = NULL;
  906. }
  907.  
  908.  
  909.  
  910. BltCanvas::~BltCanvas() {
  911.   if (hdc == NULL) return;
  912.  
  913.   // kill the bitmap and its DC
  914.   SelectObject(hdc, prevbmp);
  915.   DeleteDC(hdc);
  916.   hdc = NULL;
  917.   if (ourbmp) {
  918.     GdiFlush();
  919.     DeleteObject(hbmp);
  920.   }
  921.   if (skinbmps) {
  922.     if (skinbmps->getNumItems() > 0) {
  923.       OutputDebugString("disposeSkinBitmap not called for makeSkinBitmap, deleting the clone\n");
  924.       skinbmps->deleteAll();
  925.     }
  926.     delete skinbmps;
  927.   }
  928.   if (envelope)
  929.     delete envelope;
  930. }
  931.  
  932. BltCanvas::BltCanvas(HBITMAP bmp) {
  933.   prevbmp = NULL;
  934.   bits = NULL;
  935.   fcoord = TRUE;
  936.   ourbmp = FALSE;
  937.   skinbmps=NULL;
  938.   envelope = NULL;
  939.   
  940.   hbmp = bmp;
  941.   ASSERT(hbmp != NULL);
  942.  
  943.   // create tha DC
  944.   hdc = CreateCompatibleDC(NULL);
  945.   prevbmp = (HBITMAP)SelectObject(hdc, hbmp);
  946. }
  947.  
  948. BltCanvas::BltCanvas(int w, int h, int nb_bpp, unsigned char *pal, int palsize){
  949.  
  950.   hbmp = NULL;
  951.   prevbmp = NULL;
  952.   bits = NULL;
  953.   fcoord = TRUE;
  954.   ourbmp = TRUE;
  955.   bpp = nb_bpp;
  956.   skinbmps=NULL;
  957.   envelope = NULL;
  958.  
  959.   ASSERT(w != 0 && h != 0);
  960.   if (w==0) w=1;
  961.   if (h==0) h=1;
  962.  
  963.     static struct
  964.     {
  965.         BITMAPINFO bmi;
  966.         RGBQUAD more_bm7iColors[256];
  967.     } bitmap;
  968.   
  969. //  BITMAPINFO bmi;
  970.   ZeroMemory(&bitmap, sizeof bitmap);
  971.     if(pal)
  972.     {
  973.         for (int c = 0; c < palsize/(3); c ++) {
  974.             bitmap.bmi.bmiColors[c].rgbRed = pal[c*3];
  975.             bitmap.bmi.bmiColors[c].rgbGreen = pal[c*3+1];
  976.             bitmap.bmi.bmiColors[c].rgbBlue = pal[c*3+2];
  977.             bitmap.bmi.bmiColors[c].rgbReserved = 0;
  978.         }
  979.         bitmap.bmi.bmiHeader.biClrUsed = palsize/(3);
  980.         bitmap.bmi.bmiHeader.biClrImportant = palsize/(3);
  981.     }
  982.     else
  983.     {
  984.       bitmap.bmi.bmiHeader.biClrUsed = 0;
  985.         bitmap.bmi.bmiHeader.biClrImportant = 0;
  986.     }
  987.   bitmap.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  988.   bitmap.bmi.bmiHeader.biWidth = ABS(w);
  989.   bitmap.bmi.bmiHeader.biHeight = -ABS(h);
  990.   bitmap.bmi.bmiHeader.biPlanes = 1;
  991.   bitmap.bmi.bmiHeader.biBitCount = nb_bpp;
  992.   bitmap.bmi.bmiHeader.biCompression = BI_RGB;
  993.   bitmap.bmi.bmiHeader.biSizeImage = 0;
  994.   bitmap.bmi.bmiHeader.biXPelsPerMeter = 0;
  995.   bitmap.bmi.bmiHeader.biYPelsPerMeter = 0;
  996.   GdiFlush();
  997.   hbmp = CreateDIBSection(NULL, &bitmap.bmi, DIB_RGB_COLORS, &bits, NULL, 0);
  998.   if (hbmp == NULL) {
  999.     return;
  1000.   }
  1001.   GetObject(hbmp, sizeof(BITMAP), &bm);
  1002.   width=bm.bmWidth;
  1003.   height=ABS(bm.bmHeight);
  1004.   pitch=bm.bmWidthBytes;
  1005.  
  1006.   // create tha DC
  1007.   hdc = CreateCompatibleDC(NULL);
  1008.   if (!hdc) __asm int 3;
  1009.   prevbmp = (HBITMAP)SelectObject(hdc, hbmp);
  1010. }
  1011.  
  1012. void *BltCanvas::getBits() {
  1013.   return bits;
  1014. }
  1015.  
  1016. HBITMAP BltCanvas::getBitmap() {
  1017.   return hbmp;
  1018. }
  1019.  
  1020. SkinBitmap *BltCanvas::getSkinBitmap() { 
  1021.     // make a SkinBitmap envelope
  1022.   if (!envelope)
  1023.       envelope = new SkinBitmap(getBitmap(), getHDC(), 1, getBits());
  1024.  
  1025.   // do not delete enveloppe, it's deleted in destructor
  1026.   return envelope;
  1027. }
  1028.  
  1029. SkinBitmap *BltCanvas::makeSkinBitmap() { 
  1030.     // make a clone of the bitmap - JF> what was that crap about envelopes?
  1031.     SkinBitmap *clone = new SkinBitmap(getBitmap(), getHDC(), 1);
  1032.  
  1033.     if (!skinbmps)
  1034.       skinbmps = new PtrList<SkinBitmap>;
  1035.     skinbmps->addItem(clone);
  1036.  
  1037.     return clone;
  1038. }
  1039.  
  1040. void BltCanvas::disposeSkinBitmap(SkinBitmap *b) {
  1041.   if (skinbmps->haveItem(b)) {
  1042.     skinbmps->removeItem(b);
  1043.     delete b;
  1044.   } else {
  1045.     OutputDebugString("disposeSkinBitmap called on unknownj pointer, you should call it from the object used to makeSkinBitmap()\n");
  1046.   }
  1047. }
  1048.  
  1049. void BltCanvas::fillBits(COLORREF color) {
  1050.   // TODO: use rep movsl
  1051.   if (bpp == 32) {    // clear out the bits
  1052.     int nwords = bm.bmWidth * bm.bmHeight;
  1053.     DWORD *dwbits = (DWORD *)bits;
  1054.     for (int i = 0; i < nwords; i++) *dwbits++ = color;
  1055.   }
  1056. }
  1057.  
  1058. void BltCanvas::vflip() {
  1059.   ASSERT(bits != NULL);
  1060. //  BITMAP bm;
  1061. //  int r = GetObject(hbmp, sizeof(BITMAP), &bm);
  1062. //  if (r == 0) return;
  1063.   int w = bm.bmWidth, h = bm.bmHeight;
  1064.   int bytes = 4 * w;
  1065.   char *tmpbuf = (char *)MALLOC(bytes);
  1066.   for (int i = 0; i < h/2; i++) {
  1067.     char *p1, *p2;
  1068.     p1 = (char *)bits + bytes * i;
  1069.     p2 = (char *)bits + bytes * ((h - 1) - i);
  1070.     if (p1 == p2) continue;
  1071.     MEMCPY(tmpbuf, p1, bytes);
  1072.     MEMCPY(p1, p2, bytes);
  1073.     MEMCPY(p2, tmpbuf, bytes);
  1074.   }
  1075.   FREE(tmpbuf);
  1076. }
  1077.  
  1078. void BltCanvas::maskColor(COLORREF from, COLORREF to) {
  1079.   int n = bm.bmWidth * bm.bmHeight;
  1080.   GdiFlush();
  1081.   DWORD *b = (DWORD *)getBits();
  1082.   from &= 0xffffff;
  1083.   while (n--) {
  1084.     if ((*b & 0xffffff) == from) {
  1085.       *b = to;
  1086.     } else *b |= 0xff000000;    // force all other pixels non masked
  1087.     b++;
  1088.   }
  1089. }
  1090.  
  1091. DDSurfaceCanvas::DDSurfaceCanvas(LPDIRECTDRAWSURFACE surface, int w, int h) {
  1092.   surf = surface;
  1093.   _w = w;
  1094.   _h = h;  
  1095.   hdc = NULL;
  1096.   bits = NULL;
  1097. }
  1098.  
  1099. DDSurfaceCanvas::~DDSurfaceCanvas() {
  1100.   if (isready())
  1101.     exit();
  1102. }
  1103.  
  1104. int DDSurfaceCanvas::isready() {
  1105.   return bits != NULL;
  1106. }
  1107.  
  1108. void DDSurfaceCanvas::enter() {
  1109.   DDSURFACEDESC d={sizeof(d),};
  1110.   if ((surf->Lock(NULL,&d,DDLOCK_WAIT,NULL)) != DD_OK)
  1111.     return;
  1112.  
  1113.   surf->GetDC(&hdc);
  1114.  
  1115.   bits = d.lpSurface;
  1116. }
  1117.  
  1118. void DDSurfaceCanvas::exit() {
  1119.   surf->ReleaseDC(hdc);
  1120.   surf->Unlock(bits);
  1121.   bits = NULL;
  1122.   hdc = NULL;
  1123. }
  1124.  
  1125.  
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133.  
  1134.  
  1135.  
  1136.  
  1137.